{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Agent Executor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "String userHomeDir = System.getProperty(\"user.home\");\n",
    "String localRespoUrl = \"file://\" + userHomeDir + \"/.m2/repository/\";\n",
    "String langchain4jVersion = \"0.36.2\";\n",
    "String langgraph4jVersion = \"1.4-SNAPSHOT\";"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Remove installed package from Jupiter cache"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash \n",
    "rm -rf \\{userHomeDir}/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/bsc/langgraph4j"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "add local maven repo and install dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[0mRepository \u001b[1m\u001b[32mlocal\u001b[0m url: \u001b[1m\u001b[32mfile:///Users/bsorrentino/.m2/repository/\u001b[0m added.\n",
      "\u001b[0mAdding dependency \u001b[0m\u001b[1m\u001b[32morg.slf4j:slf4j-jdk14:2.0.9\n",
      "\u001b[0mAdding dependency \u001b[0m\u001b[1m\u001b[32morg.bsc.langgraph4j:langgraph4j-core:1.3-SNAPSHOT\n",
      "\u001b[0mAdding dependency \u001b[0m\u001b[1m\u001b[32morg.bsc.langgraph4j:langgraph4j-langchain4j:1.3-SNAPSHOT\n",
      "\u001b[0mAdding dependency \u001b[0m\u001b[1m\u001b[32morg.bsc.langgraph4j:langgraph4j-agent-executor:1.3-SNAPSHOT\n",
      "\u001b[0mAdding dependency \u001b[0m\u001b[1m\u001b[32mdev.langchain4j:langchain4j:0.36.2\n",
      "\u001b[0mAdding dependency \u001b[0m\u001b[1m\u001b[32mdev.langchain4j:langchain4j-open-ai:0.36.2\n",
      "\u001b[0mSolving dependencies\n",
      "Resolved artifacts count: 64\n",
      "Add to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/slf4j/slf4j-jdk14/2.0.9/slf4j-jdk14-2.0.9.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/bsc/langgraph4j/langgraph4j-core/1.3-SNAPSHOT/langgraph4j-core-1.3-SNAPSHOT.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/bsc/async/async-generator/3.0.0/async-generator-3.0.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/bsc/langgraph4j/langgraph4j-langchain4j/1.3-SNAPSHOT/langgraph4j-langchain4j-1.3-SNAPSHOT.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/bsc/langgraph4j/langgraph4j-agent-executor/1.3-SNAPSHOT/langgraph4j-agent-executor-1.3-SNAPSHOT.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/dev/langchain4j/langchain4j-azure-open-ai/0.36.2/langchain4j-azure-open-ai-0.36.2.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/azure/azure-ai-openai/1.0.0-beta.11/azure-ai-openai-1.0.0-beta.11.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/azure/azure-core/1.51.0/azure-core-1.51.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/azure/azure-json/1.2.0/azure-json-1.2.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/azure/azure-xml/1.1.0/azure-xml-1.1.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.17.2/jackson-datatype-jsr310-2.17.2.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/projectreactor/reactor-core/3.4.38/reactor-core-3.4.38.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/reactivestreams/reactive-streams/1.0.4/reactive-streams-1.0.4.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/azure/azure-core-http-netty/1.15.3/azure-core-http-netty-1.15.3.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-transport-native-kqueue/4.1.110.Final/netty-transport-native-kqueue-4.1.110.Final-osx-x86_64.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-transport-classes-kqueue/4.1.110.Final/netty-transport-classes-kqueue-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-tcnative-boringssl-static/2.0.65.Final/netty-tcnative-boringssl-static-2.0.65.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-tcnative-classes/2.0.65.Final/netty-tcnative-classes-2.0.65.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-tcnative-boringssl-static/2.0.65.Final/netty-tcnative-boringssl-static-2.0.65.Final-linux-x86_64.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-tcnative-boringssl-static/2.0.65.Final/netty-tcnative-boringssl-static-2.0.65.Final-linux-aarch_64.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-tcnative-boringssl-static/2.0.65.Final/netty-tcnative-boringssl-static-2.0.65.Final-osx-x86_64.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-tcnative-boringssl-static/2.0.65.Final/netty-tcnative-boringssl-static-2.0.65.Final-osx-aarch_64.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-tcnative-boringssl-static/2.0.65.Final/netty-tcnative-boringssl-static-2.0.65.Final-windows-x86_64.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/projectreactor/netty/reactor-netty-http/1.0.45/reactor-netty-http-1.0.45.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-resolver-dns/4.1.109.Final/netty-resolver-dns-4.1.109.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-codec-dns/4.1.109.Final/netty-codec-dns-4.1.109.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-resolver-dns-native-macos/4.1.109.Final/netty-resolver-dns-native-macos-4.1.109.Final-osx-x86_64.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-resolver-dns-classes-macos/4.1.109.Final/netty-resolver-dns-classes-macos-4.1.109.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/projectreactor/netty/reactor-netty-core/1.0.45/reactor-netty-core-1.0.45.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-transport-native-epoll/4.1.110.Final/netty-transport-native-epoll-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-transport-native-unix-common/4.1.110.Final/netty-transport-native-unix-common-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-transport-classes-epoll/4.1.110.Final/netty-transport-classes-epoll-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-codec-http2/4.1.110.Final/netty-codec-http2-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-transport/4.1.110.Final/netty-transport-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-common/4.1.115.Final/netty-common-4.1.115.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-resolver/4.1.110.Final/netty-resolver-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-handler-proxy/4.1.110.Final/netty-handler-proxy-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-codec-socks/4.1.110.Final/netty-codec-socks-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-codec-http/4.1.110.Final/netty-codec-http-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-buffer/4.1.110.Final/netty-buffer-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-codec/4.1.110.Final/netty-codec-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/io/netty/netty-handler/4.1.110.Final/netty-handler-4.1.110.Final.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/dev/langchain4j/langchain4j/0.36.2/langchain4j-0.36.2.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/dev/langchain4j/langchain4j-core/0.36.2/langchain4j-core-0.36.2.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/google/code/gson/gson/2.10.1/gson-2.10.1.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/apache/opennlp/opennlp-tools/1.9.4/opennlp-tools-1.9.4.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/dev/langchain4j/langchain4j-open-ai/0.36.2/langchain4j-open-ai-0.36.2.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/dev/ai4j/openai4j/0.23.0/openai4j-0.23.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/squareup/retrofit2/retrofit/2.9.0/retrofit-2.9.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/squareup/retrofit2/converter-jackson/2.9.0/converter-jackson-2.9.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/fasterxml/jackson/core/jackson-databind/2.17.2/jackson-databind-2.17.2.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/fasterxml/jackson/core/jackson-annotations/2.17.2/jackson-annotations-2.17.2.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/fasterxml/jackson/core/jackson-core/2.17.2/jackson-core-2.17.2.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/squareup/okhttp3/okhttp/4.12.0/okhttp-4.12.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/squareup/okio/okio/3.6.0/okio-3.6.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/squareup/okio/okio-jvm/3.6.0/okio-jvm-3.6.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.10/kotlin-stdlib-common-1.9.10.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/squareup/okhttp3/okhttp-sse/4.12.0/okhttp-sse-4.12.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.9.25/kotlin-stdlib-jdk8-1.9.25.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/jetbrains/kotlin/kotlin-stdlib/1.9.25/kotlin-stdlib-1.9.25.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/jetbrains/annotations/13.0/annotations-13.0.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.25/kotlin-stdlib-jdk7-1.9.25.jar\u001b[0m\n",
      "\u001b[0mAdd to classpath: \u001b[0m\u001b[32m/Users/bsorrentino/Library/Jupyter/kernels/rapaio-jupyter-kernel/mima_cache/com/knuddels/jtokkit/1.1.0/jtokkit-1.1.0.jar\u001b[0m\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "%dependency /add-repo local \\{localRespoUrl} release|never snapshot|always\n",
    "// %dependency /list-repos\n",
    "%dependency /add org.slf4j:slf4j-jdk14:2.0.9\n",
    "%dependency /add org.bsc.langgraph4j:langgraph4j-core:\\{langgraph4jVersion}\n",
    "%dependency /add org.bsc.langgraph4j:langgraph4j-langchain4j:\\{langgraph4jVersion}\n",
    "%dependency /add org.bsc.langgraph4j:langgraph4j-agent-executor:\\{langgraph4jVersion}\n",
    "%dependency /add dev.langchain4j:langchain4j:\\{langchain4jVersion}\n",
    "%dependency /add dev.langchain4j:langchain4j-open-ai:\\{langchain4jVersion}\n",
    "\n",
    "%dependency /resolve"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Initialize Logger**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "try( var file = new java.io.FileInputStream(\"./logging.properties\")) {\n",
    "    var lm = java.util.logging.LogManager.getLogManager();\n",
    "    lm.checkAccess(); \n",
    "    lm.readConfiguration( file );\n",
    "}\n",
    "\n",
    "var log = org.slf4j.LoggerFactory.getLogger(\"AgentExecutor\");\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create Tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import dev.langchain4j.agent.tool.P;\n",
    "import dev.langchain4j.agent.tool.Tool;\n",
    "\n",
    "import java.util.Optional;\n",
    "\n",
    "import static java.lang.String.format;\n",
    "\n",
    "public class TestTool {\n",
    "    private String lastResult;\n",
    "\n",
    "    Optional<String> lastResult() {\n",
    "        return Optional.ofNullable(lastResult);\n",
    "    }\n",
    "\n",
    "    @Tool(\"tool for test AI agent executor\")\n",
    "    String execTest(@P(\"test message\") String message) {\n",
    "\n",
    "        lastResult = format( \"test tool executed: %s\", message);\n",
    "        return lastResult;\n",
    "    }\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import static org.bsc.langgraph4j.StateGraph.END;\n",
    "import static org.bsc.langgraph4j.StateGraph.START;\n",
    "import org.bsc.langgraph4j.CompileConfig;\n",
    "import org.bsc.langgraph4j.RunnableConfig;\n",
    "import org.bsc.langgraph4j.checkpoint.BaseCheckpointSaver;\n",
    "import org.bsc.langgraph4j.checkpoint.MemorySaver;\n",
    "import org.bsc.langgraph4j.state.AgentState;\n",
    "import org.bsc.langgraph4j.serializer.StateSerializer;\n",
    "\n",
    "import org.bsc.langgraph4j.agentexecutor.AgentExecutor;\n",
    "\n",
    "import dev.langchain4j.model.openai.OpenAiChatModel;\n",
    "\n",
    "import java.util.List;\n",
    "import java.util.Map;\n",
    "import java.util.stream.Collectors;\n",
    "\n",
    "\n",
    "\n",
    "var chatLanguageModel = OpenAiChatModel.builder()\n",
    "    .apiKey( System.getenv(\"OPENAI_API_KEY\") )\n",
    "    //.modelName( \"gpt-3.5-turbo-0125\" )\n",
    "    .modelName( \"gpt-4o-mini\" )\n",
    "    .logResponses(true)\n",
    "    .maxRetries(2)\n",
    "    .temperature(0.0)\n",
    "    .maxTokens(2000)\n",
    "    .build();\n",
    "\n",
    "var stateGraph = AgentExecutor.graphBuilder()\n",
    "        .chatLanguageModel(chatLanguageModel)\n",
    "        .objectsWithTools(List.of(new TestTool()))\n",
    "        .build();\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test 1 \n",
    "Update State replacing the 'input'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "START \n",
      "callAgent \n",
      "STEP: NodeOutput{node=__START__, state={input=perform test once, intermediate_steps=[]}} \n",
      "executeTools \n",
      "execute: execTest \n",
      "STEP: StateSnapshot{node=agent, state={input=perform test once, intermediate_steps=[], agent_outcome=AgentOutcome[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], finish=null]}, config=RunnableConfig(threadId=test1, checkPointId=efaea448-fa00-4b2e-a49c-12672784d89c, nextNode=action, streamMode=SNAPSHOTS)} \n",
      "callAgent \n",
      "STEP: StateSnapshot{node=action, state={input=perform test once, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once]], agent_outcome=AgentOutcome[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], finish=null]}, config=RunnableConfig(threadId=test1, checkPointId=931e84ce-9b4d-4edf-85e5-01fb93641dc9, nextNode=agent, streamMode=SNAPSHOTS)} \n",
      "STEP: StateSnapshot{node=agent, state={input=perform test once, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once]], agent_outcome=AgentOutcome[action=null, finish=AgentFinish[returnValues={returnValues=The test has been executed with the message: \"perform test once\".}, log=The test has been executed with the message: \"perform test once\".]]}, config=RunnableConfig(threadId=test1, checkPointId=2d01d052-06a9-444e-9b4a-afa05c78a0c9, nextNode=__END__, streamMode=SNAPSHOTS)} \n",
      "STEP: NodeOutput{node=__END__, state={input=perform test once, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once]], agent_outcome=AgentOutcome[action=null, finish=AgentFinish[returnValues={returnValues=The test has been executed with the message: \"perform test once\".}, log=The test has been executed with the message: \"perform test once\".]]}} \n"
     ]
    }
   ],
   "source": [
    "var saver = new MemorySaver();\n",
    "\n",
    "CompileConfig compileConfig = CompileConfig.builder()\n",
    "                .checkpointSaver( saver )\n",
    "                .build();\n",
    "\n",
    "var graph = stateGraph.compile( compileConfig );\n",
    "\n",
    "var config = RunnableConfig.builder()\n",
    "                .threadId(\"test1\")\n",
    "                .build();    \n",
    "                \n",
    "var iterator = graph.streamSnapshots( Map.of( \"input\", \"perform test once\" ), config );  \n",
    "\n",
    "for( var step : iterator ) {\n",
    "    log.info( \"STEP: {}\", step );\n",
    "}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "RESUME REQUEST \n",
      "RESUME FROM agent \n",
      "executeTools \n",
      "execute: execTest \n",
      "callAgent \n",
      "STEP:\n",
      " StateSnapshot{node=action, state={input=perform test twice, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once]], agent_outcome=AgentOutcome[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], finish=null]}, config=RunnableConfig(threadId=test1, checkPointId=08ada6be-42fc-4381-acbf-a5fbc9b8e673, nextNode=agent, streamMode=SNAPSHOTS)} \n",
      "executeTools \n",
      "execute: execTest \n",
      "STEP:\n",
      " StateSnapshot{node=agent, state={input=perform test twice, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once]], agent_outcome=AgentOutcome[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_rhnSgT4hfmtFzpiHkmmeFq3w\", name = \"execTest\", arguments = \"{\"message\":\"perform test again\"}\" }, log=], finish=null]}, config=RunnableConfig(threadId=test1, checkPointId=2a5866ea-f9e8-4b13-a268-bbe7219e84fd, nextNode=action, streamMode=SNAPSHOTS)} \n",
      "callAgent \n",
      "STEP:\n",
      " StateSnapshot{node=action, state={input=perform test twice, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once], IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_rhnSgT4hfmtFzpiHkmmeFq3w\", name = \"execTest\", arguments = \"{\"message\":\"perform test again\"}\" }, log=], observation=test tool executed: perform test again]], agent_outcome=AgentOutcome[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_rhnSgT4hfmtFzpiHkmmeFq3w\", name = \"execTest\", arguments = \"{\"message\":\"perform test again\"}\" }, log=], finish=null]}, config=RunnableConfig(threadId=test1, checkPointId=766849ff-aba6-4727-b0a0-e5f5f7dc13f6, nextNode=agent, streamMode=SNAPSHOTS)} \n",
      "STEP:\n",
      " StateSnapshot{node=agent, state={input=perform test twice, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once], IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_rhnSgT4hfmtFzpiHkmmeFq3w\", name = \"execTest\", arguments = \"{\"message\":\"perform test again\"}\" }, log=], observation=test tool executed: perform test again]], agent_outcome=AgentOutcome[action=null, finish=AgentFinish[returnValues={returnValues=The tests have been executed successfully:\n",
      "\n",
      "1. **Test 1:** \"perform test once\" - Result: test tool executed.\n",
      "2. **Test 2:** \"perform test again\" - Result: test tool executed.}, log=The tests have been executed successfully:\n",
      "\n",
      "1. **Test 1:** \"perform test once\" - Result: test tool executed.\n",
      "2. **Test 2:** \"perform test again\" - Result: test tool executed.]]}, config=RunnableConfig(threadId=test1, checkPointId=be9287f9-210d-4690-b676-8aab4da44980, nextNode=__END__, streamMode=SNAPSHOTS)} \n",
      "STEP:\n",
      " NodeOutput{node=__END__, state={input=perform test twice, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_yPECPvdBFPA3GSrnVL2eUtab\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once], IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_rhnSgT4hfmtFzpiHkmmeFq3w\", name = \"execTest\", arguments = \"{\"message\":\"perform test again\"}\" }, log=], observation=test tool executed: perform test again]], agent_outcome=AgentOutcome[action=null, finish=AgentFinish[returnValues={returnValues=The tests have been executed successfully:\n",
      "\n",
      "1. **Test 1:** \"perform test once\" - Result: test tool executed.\n",
      "2. **Test 2:** \"perform test again\" - Result: test tool executed.}, log=The tests have been executed successfully:\n",
      "\n",
      "1. **Test 1:** \"perform test once\" - Result: test tool executed.\n",
      "2. **Test 2:** \"perform test again\" - Result: test tool executed.]]}} \n"
     ]
    }
   ],
   "source": [
    "var history = graph.getStateHistory(config).stream().collect( Collectors.toList() );\n",
    "\n",
    "var state2 =  history.get(2);\n",
    "\n",
    "var updatedConfig = graph.updateState( state2.config(), Map.of( \"input\", \"perform test twice\"), null);\n",
    "\n",
    "var iterator = graph.streamSnapshots( null, updatedConfig );  \n",
    "\n",
    "for( var step : iterator ) {\n",
    "    log.info( \"STEP:\\n {}\", step );\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test 2\n",
    "Update State replacing the 'input' using a cloned state"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "START \n",
      "callAgent \n",
      "STEP: NodeOutput{node=__START__, state={input=perform test once, intermediate_steps=[]}} \n",
      "executeTools \n",
      "execute: execTest \n",
      "STEP: StateSnapshot{node=agent, state={input=perform test once, intermediate_steps=[], agent_outcome=AgentOutcome[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], finish=null]}, config=RunnableConfig(threadId=test2, checkPointId=ca5489e0-0b54-4e93-8aaf-f7c91d539d5a, nextNode=action, streamMode=SNAPSHOTS)} \n",
      "callAgent \n",
      "STEP: StateSnapshot{node=action, state={input=perform test once, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once]], agent_outcome=AgentOutcome[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], finish=null]}, config=RunnableConfig(threadId=test2, checkPointId=39ea80cb-8d1e-48cb-ab3d-49bc41d3dd1c, nextNode=agent, streamMode=SNAPSHOTS)} \n",
      "STEP: StateSnapshot{node=agent, state={input=perform test once, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once]], agent_outcome=AgentOutcome[action=null, finish=AgentFinish[returnValues={returnValues=The test has been executed with the message: \"perform test once\".}, log=The test has been executed with the message: \"perform test once\".]]}, config=RunnableConfig(threadId=test2, checkPointId=7c9868e2-8aa7-4986-a717-a757f9574684, nextNode=__END__, streamMode=SNAPSHOTS)} \n",
      "STEP: NodeOutput{node=__END__, state={input=perform test once, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once]], agent_outcome=AgentOutcome[action=null, finish=AgentFinish[returnValues={returnValues=The test has been executed with the message: \"perform test once\".}, log=The test has been executed with the message: \"perform test once\".]]}} \n"
     ]
    }
   ],
   "source": [
    "\n",
    "var config = RunnableConfig.builder()\n",
    "                .threadId(\"test2\")\n",
    "                .build();    \n",
    "                \n",
    "var iterator = graph.streamSnapshots( Map.of( \"input\", \"perform test once\" ), config );  \n",
    "\n",
    "for( var step : iterator ) {\n",
    "    log.info( \"STEP: {}\", step );\n",
    "}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "UPDATED CONFIG: RunnableConfig(threadId=test2, checkPointId=ca5489e0-0b54-4e93-8aaf-f7c91d539d5a, nextNode=null, streamMode=VALUES) \n",
      "RESUME REQUEST \n",
      "RESUME FROM agent \n",
      "executeTools \n",
      "execute: execTest \n",
      "callAgent \n",
      "STEP:\n",
      " StateSnapshot{node=action, state={input=perform test twice, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once]], agent_outcome=AgentOutcome[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], finish=null]}, config=RunnableConfig(threadId=test2, checkPointId=c324eeac-5109-4f9e-b4a3-d3617d7ec360, nextNode=agent, streamMode=SNAPSHOTS)} \n",
      "executeTools \n",
      "execute: execTest \n",
      "STEP:\n",
      " StateSnapshot{node=agent, state={input=perform test twice, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once]], agent_outcome=AgentOutcome[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_kdsuye0KybTCqRa4Ehe9cJeF\", name = \"execTest\", arguments = \"{\"message\":\"perform test again\"}\" }, log=], finish=null]}, config=RunnableConfig(threadId=test2, checkPointId=67e28047-b81c-4301-9a00-d0c227bac922, nextNode=action, streamMode=SNAPSHOTS)} \n",
      "callAgent \n",
      "STEP:\n",
      " StateSnapshot{node=action, state={input=perform test twice, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once], IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_kdsuye0KybTCqRa4Ehe9cJeF\", name = \"execTest\", arguments = \"{\"message\":\"perform test again\"}\" }, log=], observation=test tool executed: perform test again]], agent_outcome=AgentOutcome[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_kdsuye0KybTCqRa4Ehe9cJeF\", name = \"execTest\", arguments = \"{\"message\":\"perform test again\"}\" }, log=], finish=null]}, config=RunnableConfig(threadId=test2, checkPointId=329a295c-b284-4e5b-bfee-b0c6c924691c, nextNode=agent, streamMode=SNAPSHOTS)} \n",
      "STEP:\n",
      " StateSnapshot{node=agent, state={input=perform test twice, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once], IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_kdsuye0KybTCqRa4Ehe9cJeF\", name = \"execTest\", arguments = \"{\"message\":\"perform test again\"}\" }, log=], observation=test tool executed: perform test again]], agent_outcome=AgentOutcome[action=null, finish=AgentFinish[returnValues={returnValues=The tests have been executed successfully:\n",
      "\n",
      "1. **Test 1:** \"perform test once\" - Result: test tool executed.\n",
      "2. **Test 2:** \"perform test again\" - Result: test tool executed.}, log=The tests have been executed successfully:\n",
      "\n",
      "1. **Test 1:** \"perform test once\" - Result: test tool executed.\n",
      "2. **Test 2:** \"perform test again\" - Result: test tool executed.]]}, config=RunnableConfig(threadId=test2, checkPointId=f496b8dd-c822-4ab6-b5ea-5408d7abf4eb, nextNode=__END__, streamMode=SNAPSHOTS)} \n",
      "STEP:\n",
      " NodeOutput{node=__END__, state={input=perform test twice, intermediate_steps=[IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_vgNCAcj6yMWaOQ2GxRW7EfKu\", name = \"execTest\", arguments = \"{\"message\":\"perform test once\"}\" }, log=], observation=test tool executed: perform test once], IntermediateStep[action=AgentAction[toolExecutionRequest=ToolExecutionRequest { id = \"call_kdsuye0KybTCqRa4Ehe9cJeF\", name = \"execTest\", arguments = \"{\"message\":\"perform test again\"}\" }, log=], observation=test tool executed: perform test again]], agent_outcome=AgentOutcome[action=null, finish=AgentFinish[returnValues={returnValues=The tests have been executed successfully:\n",
      "\n",
      "1. **Test 1:** \"perform test once\" - Result: test tool executed.\n",
      "2. **Test 2:** \"perform test again\" - Result: test tool executed.}, log=The tests have been executed successfully:\n",
      "\n",
      "1. **Test 1:** \"perform test once\" - Result: test tool executed.\n",
      "2. **Test 2:** \"perform test again\" - Result: test tool executed.]]}} \n"
     ]
    }
   ],
   "source": [
    "var history = graph.getStateHistory(config).stream().collect( Collectors.toList() );\n",
    "\n",
    "var state2 =  history.get(2);\n",
    "\n",
    "var updatedState = new HashMap<String,Object>();\n",
    "updatedState.putAll(state2.state().data());\n",
    "\n",
    "//System.out.println( state2.state().data() );\n",
    "updatedState.put(  \"input\", \"perform test twice\"  );\n",
    "//System.out.println( updatedState );\n",
    "\n",
    "var updatedConfig = graph.updateState( state2.config(), updatedState );\n",
    "log.info( \"UPDATED CONFIG: {}\", updatedConfig );\n",
    "\n",
    "var iterator = graph.streamSnapshots( null, updatedConfig );  \n",
    "\n",
    "try {\n",
    "    for( var step : iterator ) {\n",
    "        log.info( \"STEP:\\n {}\", step );\n",
    "    }    \n",
    "}\n",
    "catch( Exception e ) {\n",
    "    Throwable t = e ;\n",
    "    while( t.getCause() != null ) {\n",
    "        t = t.getCause();\n",
    "    }\n",
    "    t.printStackTrace();\n",
    "}\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Java (rjk 2.2.0)",
   "language": "java",
   "name": "rapaio-jupyter-kernel"
  },
  "language_info": {
   "codemirror_mode": "java",
   "file_extension": ".jshell",
   "mimetype": "text/x-java-source",
   "name": "java",
   "nbconvert_exporter": "script",
   "pygments_lexer": "java",
   "version": "17.0.2+8-86"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
